#include <stdio.h>
#include "osal_debug.h"
#include "cmsis_os2.h"
#include "app_init.h"
#include "soc_osal.h"
#include "watchdog.h"
#include "ssd1306_fonts.h"
#include "ssd1306.h"
#include "i2c.h"
#include "pinctrl.h"
#include "soc_osal.h"
#include "lvgl.h"
#include "timer.h"
#include "chip_core_irq.h"
#include "font_awesome.h"




void ssd1306_set_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
void ssd1306_write_data_16bit(uint8_t *data, uint32_t len);

void ssd1306_write_data_1bit(uint8_t *data, uint32_t len);



#define XIAOZHI_TASK_STACK_SIZE 0x1000
#define XIAOZHI_TASK_PRIO (osPriorityNormal + 1)

#define I2C_MASTER_ADDR                   0x0
#define I2C_SET_BAUDRATE                  400000
#define I2C_MASTER_PIN_MODE               2

static timer_handle_t timer_handle = NULL;                     // 定时器句柄
static uint8_t buf_16bit[SSD1306_WIDTH * SSD1306_HEIGHT *2]; /*RGB565格式缓冲区，每像素2字节*/


// 为单色模式创建更合适的缓冲区
//static uint8_t buf_1bit[SSD1306_WIDTH * SSD1306_HEIGHT / 8  + 128 ]; // 单色模式，每8像素1字节，得加128扩大一下缓冲区，不然需要set_window两次
    
// lvgl刷新定时器回调
void TimerCallback(uintptr_t data)
{
    unused(data);
    lv_tick_inc(1); // 告诉LVGL时间过去1毫秒
    uapi_timer_start(timer_handle, 1000, TimerCallback, 0);
}



static void disp_flush(lv_display_t *disp_drv, const lv_area_t *area, uint8_t *px_map)
{
    // osal_printk("disp_flush called: area(%d,%d)-(%d,%d), size=%d bytes\n", 
    //             area->x1, area->y1, area->x2, area->y2, 
    //             (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1) * 2);
    
    ssd1306_set_window(area->x1, area->y1, area->x2, area->y2);
    ssd1306_write_data_16bit(px_map, (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1) *2 ); // 每个像素2字节
    lv_display_flush_ready(disp_drv);
}


static void app_i2c_init_pin(void)
{
    /* I2C pinmux. */
    uapi_pin_set_mode(15, I2C_MASTER_PIN_MODE);
    uapi_pin_set_mode(16, I2C_MASTER_PIN_MODE);       
    uapi_pin_set_pull(15, PIN_PULL_TYPE_UP);
    uapi_pin_set_pull(16, PIN_PULL_TYPE_UP);
}

static void xiaozhi_task(void)
{
    app_i2c_init_pin();
    errcode_t ret = uapi_i2c_master_init(1, I2C_SET_BAUDRATE, I2C_MASTER_ADDR);
    if (ret != 0) {
        printf("i2c init failed, ret = %0x\r\n", ret);
    }
    ssd1306_Init();
    ssd1306_Fill(Black);
    ssd1306_UpdateScreen();  // 初始化后更新一次屏幕

    lv_init();

    lv_display_t *disp = lv_display_create(SSD1306_WIDTH, SSD1306_HEIGHT);
    lv_display_set_flush_cb(disp, disp_flush);
    lv_display_set_buffers(disp, buf_16bit, NULL, sizeof(buf_16bit), LV_DISPLAY_RENDER_MODE_PARTIAL);

    uapi_timer_init();                                             // 初始化定时器模块
    uapi_timer_adapter(1, TIMER_1_IRQN, 1); // 配置lvgl定时器适配器
    uapi_timer_create(1, &timer_handle);                 // 创建lvgl定时器，并获取定时器句柄
    uapi_timer_start(timer_handle, 1000, TimerCallback, 0);     // 启动lvgl定时器，设置触发时间和回调函数


    /*                    顶部状态栏                         */

    // 创建顶部状态栏容器（0，0）->(127，30)
    uint16_t container_status_width = 127 - 0 + 1; // 128像素
    uint16_t container_status_height = 30 - 0 + 1; // 31像素

    lv_obj_t *container_status = lv_obj_create(lv_scr_act());
    lv_obj_set_size(container_status, container_status_width, container_status_height);
    lv_obj_set_pos(container_status, 0, 0);
 

    // 取消容器之间的间隔
    lv_obj_set_style_pad_all(container_status, 0, 0); // 设置内边距为0
    lv_obj_set_style_pad_row(container_status, 0, 0);
    lv_obj_set_style_pad_column(container_status, 0, 0);


    // 在顶部容器中添加内容

    // 语音状态
    lv_obj_t *label_status = lv_label_create(container_status);
    lv_label_set_text(label_status, "聆听中...");
    lv_obj_center(label_status);
    lv_obj_set_y(label_status, lv_obj_get_y(label_status) - 2); // 向上移动2像素
    lv_obj_set_style_bg_opa(container_status, 0, 0); 
    // 网络状态
    lv_obj_t *label_network = lv_label_create(container_status);
    lv_label_set_text(label_network, FONT_AWESOME_WIFI);
    lv_obj_align(label_network, LV_ALIGN_LEFT_MID, 5, -4); // 左侧中间对齐，x偏移5像素，y偏移0像素
    lv_obj_set_style_text_font(label_network, &font_awesome_14_1, 0);
    //和下面区域的分隔线
    lv_obj_t *label_ddl = lv_label_create(container_status);
    lv_label_set_text(label_ddl, "- - - - - - - - - - - -"); 
    lv_obj_align(label_ddl, LV_ALIGN_BOTTOM_MID, 0, 0); // 将标签对齐到容器的底部居中位置
    

    /*                    顶部状态栏                         */





    /*                    返回流动文本                       */


    // 文本区域（31，15）->(127，63)
    uint16_t text_width = 127 - 31 + 1; // 97像素
    uint16_t text_height = 63 - 15 + 1; // 49像素
    lv_obj_t *container_text = lv_obj_create(lv_scr_act());
    
    lv_obj_set_size(container_text, text_width, text_height);
    lv_obj_set_pos(container_text, 31, 15);
    lv_obj_set_style_bg_opa(container_text, 0, 0); // 透明背景,这个必须调用，不然会出问题(花屏)

    // 在容器内创建标签并居中
    lv_obj_t *label_text = lv_label_create(container_text);
    // 设置标签文本内容
    lv_label_set_text(label_text, "我是小智，这是在做滚动测试哦abcd");
    //lv_obj_set_style_text_font(label_text, &font_puhui_14_1, 0);
    // 设置动画模式
    lv_label_set_long_mode(label_text, LV_LABEL_LONG_MODE_SCROLL_CIRCULAR); // 循环滚动模式
    lv_obj_set_style_anim_duration(label_text, 1500, 0);// 设置滚动动画时长（毫秒）
    // 设置标签位置
    lv_obj_set_width(label_text, text_width - 10);// 设置标签宽度（小于容器宽度以启用滚动）
    lv_obj_set_height(label_text, 24);// 设置标签高度
    lv_obj_center(label_text); // 在容器内居中
    lv_obj_set_y(label_text, lv_obj_get_y(label_text) + 4); // 向下移动2像素
    
    

    /*                    返回流动文本                       */




    /*                    表情显示区                         */

    // 表情区域（0，16） ->(30，63)
    uint16_t emoji_width  = 30 - 0 + 1; 
    uint16_t emoji_height = 63 - 16 + 1;
    lv_obj_t *container_emoji = lv_obj_create(lv_scr_act());
    
    lv_obj_set_size(container_emoji, emoji_width, emoji_height);
    lv_obj_set_pos(container_emoji, 0, 16);

    // 创建表情标签
    lv_obj_t *label_emoji = lv_label_create(container_emoji);
    lv_label_set_text(label_emoji, FONT_AWESOME_NEUTRAL);
    lv_obj_center(label_emoji);
    lv_obj_set_style_text_font(label_emoji, &font_awesome_20_4, 0);

    /*                    表情显示区                         */
    

    while (1)
    {
        lv_timer_handler();
        uapi_watchdog_kick();
        osal_msleep(33);
        
    }
}

static void xiaozhi_entry(void)
{
    osThreadAttr_t attr;

    attr.name = "XiaozhiTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = XIAOZHI_TASK_STACK_SIZE;
    attr.priority = XIAOZHI_TASK_PRIO;

    if (osThreadNew((osThreadFunc_t)xiaozhi_task, NULL, &attr) == NULL)
    {
        printf("Failed to create xiaozhi task!\n");
    }
}

// ST7789适配SSD1306的函数实现
// 全局变量存储当前绘制区域
static lv_area_t current_area = {0};

void ssd1306_set_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
    // 保存当前绘制区域信息
    current_area.x1 = x1;
    current_area.y1 = y1;
    current_area.x2 = x2;
    current_area.y2 = y2;
    
    osal_printk("ssd1306_set_window: (%d,%d)-(%d,%d)\n", x1, y1, x2, y2);
}

void ssd1306_write_data_1bit(uint8_t *data, uint32_t len)
{
    /*刚刚的*/

    // I1 格式 ，一个字节存储8个像素点
    uint32_t pixel_count = len * 8; 
    //uint16_t *pixel_data = (uint16_t*)data;
    
    // 计算区域尺寸
    uint16_t area_width = current_area.x2 - current_area.x1 + 1;
    uint16_t area_height = current_area.y2 - current_area.y1 + 1;
    
    osal_printk("ssd1306_write_data: len=%d, pixels=%d, area=%dx%d\n", 
                len, pixel_count, area_width, area_height);

    for (uint32_t i = 0; i < pixel_count; i++) {

        // 计算像素在字节中的位置
        uint32_t byte_index = i / 8;
        uint8_t bit_index = 7 - (i % 8); // SSD1306通常是高位在前
        
        // 检查是否超出数据范围
        if (byte_index >= len) {
            break;
        }
        
        // 提取像素值（0或1）
        uint8_t pixel_value = (data[byte_index] >> bit_index) & 0x01;

        //uint16_t pixel = pixel_data[i];

        // 计算像素在区域内的相对位置
        uint16_t rel_x = i % area_width;
        uint16_t rel_y = i / area_width;
        
        // 计算在屏幕上的绝对位置（绘制左半边）
        uint16_t abs_x = current_area.x1 + rel_x - SSD1306_WIDTH / 2;
        uint16_t abs_y = current_area.y1 + rel_y;

        // 确保坐标在屏幕范围内
        if (abs_x < SSD1306_WIDTH  && abs_y < SSD1306_HEIGHT) {
            
            if (pixel_value) {  
                ssd1306_DrawPixel(abs_x, abs_y, Black);
            } else {
                ssd1306_DrawPixel(abs_x, abs_y, White);
            }
        }

        // 计算像素在区域内的相对位置（绘制右半边）
         abs_x = current_area.x1 + rel_x + SSD1306_WIDTH / 2;
         abs_y = current_area.y1 + rel_y - 1;

        if (abs_x < SSD1306_WIDTH  && abs_y < SSD1306_HEIGHT) {
            
            if (pixel_value) {  
                ssd1306_DrawPixel(abs_x, abs_y, Black);
            } else {
                ssd1306_DrawPixel(abs_x, abs_y, White);
            }
        }

    }
     osal_printk("ssd1306_write_data: processed %d pixels, updating screen\n", pixel_count);
    
    // 更新屏幕显示
    ssd1306_UpdateScreen();
    /*刚刚的*/

}

void ssd1306_write_data_16bit(uint8_t *data, uint32_t len)
{
    // LVGL使用RGB565格式，每个像素2字节
    // SSD1306是单色显示器，需要将RGB565转换为单色
    
    uint32_t pixel_count = len / 2; // RGB565格式，每像素2字节
    uint16_t *pixel_data = (uint16_t*)data;
    
    // 计算区域尺寸
    uint16_t area_width = current_area.x2 - current_area.x1 + 1;
    uint16_t area_height = current_area.y2 - current_area.y1 + 1;
    
    osal_printk("ssd1306_write_data: len=%d, pixels=%d, area=%dx%d\n", 
                len, pixel_count, area_width, area_height);
    
    // 将RGB565像素转换为单色并绘制到指定区域
    for (uint32_t i = 0; i < pixel_count; i++) {
        uint16_t pixel = pixel_data[i];
        
        // 处理字节交换（如果LVGL配置了LV_COLOR_16_SWAP）
        #if LV_COLOR_16_SWAP
        pixel = ((pixel & 0xFF) << 8) | ((pixel >> 8) & 0xFF);
        #endif
        
        // 从RGB565提取RGB分量
        uint8_t r = (pixel >> 11) & 0x1F;  // 5位红色
        uint8_t g = (pixel >> 5) & 0x3F;   // 6位绿色  
        uint8_t b = pixel & 0x1F;          // 5位蓝色
        
        // 转换为8位RGB值
        r = (r * 255) / 31;
        g = (g * 255) / 63;
        b = (b * 255) / 31;
        
        // 计算亮度（使用标准亮度公式）
        uint8_t brightness = (uint8_t)(0.299 * r + 0.587 * g + 0.114 * b);
        
        // 计算像素在区域内的相对位置
        uint16_t rel_x = i % area_width;
        uint16_t rel_y = i / area_width;
        
        // 计算在屏幕上的绝对位置
        uint16_t abs_x = current_area.x1 + rel_x;
        uint16_t abs_y = current_area.y1 + rel_y;
        
        // 确保坐标在屏幕范围内
        if (abs_x < SSD1306_WIDTH && abs_y < SSD1306_HEIGHT) {
            // 使用阈值判断是否显示像素（可以调整阈值）
            if (brightness > 128) {  // 亮度阈值，可以调整
                ssd1306_DrawPixel(abs_x, abs_y, Black);
            } else {
                ssd1306_DrawPixel(abs_x, abs_y, White);
            }
        }
    }
    
    osal_printk("ssd1306_write_data: processed %d pixels, updating screen\n", pixel_count);
    
    // 更新屏幕显示
    ssd1306_UpdateScreen();


}

// 使用应用初始化宏注册入口函数
app_run(xiaozhi_entry);